/* eslint-disable consistent-return */
/* eslint-disable func-names */
/* eslint-disable global-require */
/**
 * i18n的配置
 */
import lexicon from '@/lib/lexicon';
import utils from '@/lib/utils';
import store from '@/store/index';
import axios from 'axios';
import Vue from 'vue';
import VueI18n from 'vue-i18n';

Vue.use(VueI18n);

/**
 * 生成i18n实例
 * message为本地语言包，需懒加载
 */

const zhCN = require('../../public/lang/zh-CN.json');
const zhTW = require('../../public/lang/zh-TW.json');
const enUS = require('../../public/lang/en-US.json');

const langContext = new Map([
  ['en-US', enUS],
  ['zh-TW', zhTW],
  ['zh-CN', zhCN]
]);
const i18n: VueI18n = new VueI18n({
  locale: 'en-US', // 默认语言为英文
  fallbackLocale: 'en-US', // 默认备用语言为英文
  messages: {
    'zh-CN': zhCN,
    'zh-TW': zhTW,
    'en-US': enUS
  },
  silentTranslationWarn: true // 不显示翻译错误
});

const loadedLanguages: string[] = []; // 已加载的i18n文件
const langLibrary: string[] = ['zh-CN', 'en-US', 'zh-TW']; // 所有的支持语言

/**
 * 设置当前i18n语言
 */
const setI18nLanguage = (lang: string): string => {
  i18n.locale = lang; // 设置当前的语言
  axios.defaults.headers.common['Accept-Language'] = lang; // 设置请求头
  // 设置文档语言
  const htmlTag: HTMLHtmlElement | null = document.querySelector('html');
  // tslint:disable-next-line:no-unused-expression
  htmlTag !== null && htmlTag.setAttribute('lang', lang);
  localStorage.setItem('lang', lang); // 缓存语言
  store.commit('SET_SETLANGUAGE', lang);
  return lang;
};

const loadLanguageAsync = (lang: string) => {
  // 如果已有当前语言
  lang = langLibrary.includes(lang) ? lang : 'en-US';
  // 如果语言相同
  if (i18n.locale === lang && loadedLanguages.length !== 0) {
    return Promise.resolve(setI18nLanguage(lang));
  }
  // 如果语言已存在
  if (loadedLanguages.includes(lang)) {
    return Promise.resolve(setI18nLanguage(lang));
  }
  // 如果语言没有加载
  const timestamp: number = new Date().getTime();

  return Promise.all([
    axios.get(`${lexicon.url.getI18nPath}?langFile=${lang}.json`),
    axios.get(`${lexicon.url.getI18nPath}?langFile=msg-${lang}.json`)
  ]).then(res => {
    const md = {};
    res.forEach(r => {
      if (r?.data?.success) {
        const d = r?.data?.data;
        d &&
          typeof d === 'string' &&
          utils.isJSONString(d) &&
          (r.data.data = JSON.parse(d));
        Object.assign(md, r.data.data);
      }
    });
    i18n.mergeLocaleMessage(lang, md); // 融合语言包
    loadedLanguages.push(lang);
    return setI18nLanguage(lang);
  });
};

const loadMutiLanguageAsync = (langArr: Array<string>): Promise<boolean> => {
  return new Promise((resolve, reject) => {
    const count = langArr.length;
    count === 0 && reject(false);
    let cn: number = 0;
    const langs: Array<{ name: string; data: any }> = [];
    let allOK: boolean = true;
    const output = () => {
      if (allOK) {
        langs.forEach(r => {
          i18n.mergeLocaleMessage(r.name, r.data);
          loadedLanguages.push(r.name);
        });
        resolve(allOK);
      } else {
        reject(false);
      }
    };
    const checkCount = () => {
      cn++;
      cn === count && output();
    };

    // langArr.forEach(lang => {
    //   axios
    //     .get(`${lexicon.url.getI18nPath}?langFile=${lang}.json`)
    //     .then(res => {
    //       if (res?.data?.success) {
    //         langs.push({ name: lang, data: res.data.data });
    //         checkCount();
    //       } else {
    //         console.error(res.data.msg);
    //         allOK = false;
    //         resolve(allOK);
    //       }
    //     })
    //     .catch(r => {
    //       console.error(r);
    //       allOK = false;
    //       checkCount();
    //       reject(allOK);
    //     });
    // });
    langArr.forEach(lang => {
      Promise.all([
        axios.get(`${lexicon.url.getI18nPath}?langFile=${lang}.json`),
        axios.get(`${lexicon.url.getI18nPath}?langFile=msg-${lang}.json`)
      ])
        .then(res => {
          const d = {};
          res.forEach(r => {
            if (r?.data?.success) {
              const dd = r?.data?.data;
              dd &&
                typeof dd === 'string' &&
                utils.isJSONString(dd) &&
                (r.data.data = JSON.parse(dd));
              Object.assign(d, r.data.data);
            } else {
              console.error(r.data.msg);
              allOK = false;
              resolve(allOK);
            }
          });
          langs.push({ name: lang, data: d });
          checkCount();
        })
        .catch(r => {
          console.error(r);
          allOK = false;
          checkCount();
          reject(allOK);
        });
    });
  });
};

export const initLanguageAsync = () => {
  const userLanguage: string =
    localStorage.getItem('lang') || window.navigator.language;
  return loadLanguageAsync(userLanguage);
};

// 挂载

Vue.prototype.$languageSetter = {
  initLanguage: initLanguageAsync,
  setLanguage: loadLanguageAsync,
  loadLanguage: loadMutiLanguageAsync
};

export { VueI18n, enUS, i18n, langContext, zhCN, zhTW };
